#ifndef _LOG_HELPER_HPP
#define _LOG_HELPER_HPP

#include <stdint.h>
#include <sstream>
#include <iostream>

namespace RockLog
{
    enum LogLevel
    {
        kDisable = -1,
        kDebug = 0,
        kInfo = 1,
        kWarn = 2,
        kErr = 3,
    };

    class LogHelper
    {
    public:
        LogHelper()
        {
            _level = (int32_t)kDebug;
        }

        LogHelper(int32_t level, const char *func, uint32_t line)
            : _level(level), _funcName(func), _lineNo(line)
        {
        }

        inline LogHelper &operator<<(std::ostream &(*log)(std::ostream &))
        {
            _ss << log;
            return *this;
        }

        template <typename T>
        inline LogHelper &operator<<(const T &log)
        {
            if (_ss.str().length() > 0)
            {
                _ss << " ";
            }
            _ss << log;
            return *this;
        }

        ~LogHelper()
        {
            std::ostringstream oss;
            switch (_level)
            {
            case (int32_t)kDebug:
                oss << "[D] -";
                break;
            case (int32_t)kInfo:
                oss << "[I] -";
                break;
            case (int32_t)kWarn:
                oss << "[W] -";
                break;
            case (int32_t)kErr:
                oss << "[E] -";
                break;
            case (int32_t)kDisable:
                return;
            default:
                break;
            }

            oss << "[" << _funcName << ":" << _lineNo << "] - ";
            oss << _ss.str();
            std::cout << oss.str() << std::endl;
        }

    private:
        int32_t _level;
        std::stringstream _ss;
        std::string _funcName;
        uint32_t _lineNo;
    };

#define LOG(X) LogHelper(X, __FUNCTION__, __LINE__)
}; // namespace RockLog

#endif